package com.ctg.itrdc.imageconsole.control.ssh;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ctg.itrdc.imageconsole.common.bean.CommonResult;
import com.ctg.itrdc.imageconsole.common.bean.ReturnCodeDefine;
import com.ctg.itrdc.imageconsole.control.ssh.db.AuthDB;
import com.ctg.itrdc.imageconsole.control.ssh.db.SessionAuditDB;
import com.ctg.itrdc.imageconsole.control.ssh.db.SystemDB;
import com.ctg.itrdc.imageconsole.control.ssh.db.SystemStatusDB;
import com.ctg.itrdc.imageconsole.control.ssh.model.Auth;
import com.ctg.itrdc.imageconsole.control.ssh.model.HostSystem;
import com.ctg.itrdc.imageconsole.control.ssh.model.SchSession;
import com.ctg.itrdc.imageconsole.control.ssh.model.User;
import com.ctg.itrdc.imageconsole.control.ssh.model.UserSchSessions;
import com.ctg.itrdc.imageconsole.control.ssh.utils.AuthUtil;
import com.ctg.itrdc.imageconsole.control.ssh.utils.SSHUtil;
import com.ctg.itrdc.paspsdk.common.utils.json.JSONUtils;

/**
 * ssh连接请求，这个接口主要是提供给开发者门户使用jsonp进行跨域调用的
 * 
 * @author wupiao
 *
 */
@Controller
@RequestMapping("/sshjsonp")
public class SecureShellJsonpAction {
	private Logger logger = LoggerFactory.getLogger(this.getClass());

	HostSystem currentSystem;
	HostSystem pendingSystem;
	String password;
	String passphrase;
	HostSystem system = new HostSystem();

	static Map<Long, UserSchSessions> userSchSessionMap = new ConcurrentHashMap<>();

	@RequestMapping(value = "/createTerms", method = RequestMethod.GET)
	@ResponseBody
	public String createTerms(HttpServletRequest servletRequest, @RequestParam("callback") String callback) {
		CommonResult commonResult = null;
		currentSystem = null;
		if (AuthUtil.getUserId(servletRequest.getSession()) == null) {
			login(servletRequest);
		}
		Long userId = AuthUtil.getUserId(servletRequest.getSession());
		SystemDB.insertOrUpdateSystem();
		SystemStatusDB.setInitialSystemStatus(userId);
		pendingSystem = SystemStatusDB.getNextPendingSystem(userId);
		AuthUtil.setSessionId(servletRequest.getSession(), SessionAuditDB.createSessionLog(userId));
		if (pendingSystem == null) {
			commonResult = new CommonResult(ReturnCodeDefine.Code.C1101, ReturnCodeDefine.Msg.M1101);
			return getIncludeCallbackJson(callback, commonResult);
		}
		Long sessionId = AuthUtil.getSessionId(servletRequest.getSession());
		if (pendingSystem != null && pendingSystem.getId() != null) {
			currentSystem = SystemStatusDB.getSystemStatus(pendingSystem.getId(), userId);
			if (currentSystem != null && (HostSystem.INITIAL_STATUS.equals(currentSystem.getStatusCd())
					|| HostSystem.AUTH_FAIL_STATUS.equals(currentSystem.getStatusCd())
					|| HostSystem.PUBLIC_KEY_FAIL_STATUS.equals(currentSystem.getStatusCd()))) {
				currentSystem = SSHUtil.openSSHTermOnSystem(passphrase, password, userId, sessionId, currentSystem,
						userSchSessionMap);
			}
			if (currentSystem != null && (HostSystem.AUTH_FAIL_STATUS.equals(currentSystem.getStatusCd())
					|| HostSystem.PUBLIC_KEY_FAIL_STATUS.equals(currentSystem.getStatusCd()))) {
				pendingSystem = currentSystem;
			} else {
				pendingSystem = SystemStatusDB.getNextPendingSystem(userId);
				// if success loop through systems until finished or need
				// password
				while (pendingSystem != null && currentSystem != null
						&& HostSystem.SUCCESS_STATUS.equals(currentSystem.getStatusCd())) {
					currentSystem = SSHUtil.openSSHTermOnSystem(passphrase, password, userId, sessionId, pendingSystem,
							userSchSessionMap);
					pendingSystem = SystemStatusDB.getNextPendingSystem(userId);
				}
			}
		}
		if (SystemStatusDB.getNextPendingSystem(userId) == null) {
			if (userSchSessionMap != null && userSchSessionMap.get(sessionId) != null) {
				Map<Integer, SchSession> schSessionMap = userSchSessionMap.get(sessionId).getSchSessionMap();
				for (SchSession schSession : schSessionMap.values()) {
					system = schSession.getHostSystem();
				}
			}
		}
		commonResult = new CommonResult(ReturnCodeDefine.Code.C1000, ReturnCodeDefine.Msg.M1000, system);
		return getIncludeCallbackJson(callback, commonResult);
	}

	private String getIncludeCallbackJson(String callback, CommonResult commonResult) {
		String json = JSONUtils.toJsonString(commonResult);
		StringBuffer sb = new StringBuffer();
		sb.append(callback + "(");
		sb.append(json + ")");
		return sb.toString();
	}

	private void login(HttpServletRequest servletRequest) {
		Auth auth = new Auth();
		auth.setUsername("root");
		auth.setPassword("root");
		String authToken = AuthDB.login(auth);
		if (authToken != null) {
			User user = AuthDB.getUserByAuthToken(authToken);
			if (user != null) {
				AuthUtil.setAuthToken(servletRequest.getSession(), authToken);
				AuthUtil.setUserId(servletRequest.getSession(), user.getId());
				AuthUtil.setTimeout(servletRequest.getSession());
			}
		}
	}

	@RequestMapping(value = "/stopConnection", method = RequestMethod.GET)
	@ResponseBody
	public String stopConnection(@RequestParam("instanceId") Integer instanceId,
			@RequestParam("callback") String callback, HttpServletRequest servletRequest) {
		CommonResult commonResult = null;
		Long sessionId = AuthUtil.getSessionId(servletRequest.getSession());
		if (SecureShellJsonpAction.getUserSchSessionMap() != null) {
			UserSchSessions userSchSessions = SecureShellJsonpAction.getUserSchSessionMap().get(sessionId);
			if (userSchSessions != null) {
				try {
					SchSession schSession = userSchSessions.getSchSessionMap().get(instanceId);
					if (schSession != null) {
						if (schSession.getChannel() != null)
							schSession.getChannel().disconnect();
						if (schSession.getSession() != null)
							schSession.getSession().disconnect();
						schSession.setChannel(null);
						schSession.setSession(null);
						schSession.setInputToChannel(null);
						schSession.setCommander(null);
						schSession.setOutFromChannel(null);
					}
					userSchSessions.getSchSessionMap().remove(instanceId);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
					commonResult = new CommonResult(ReturnCodeDefine.Code.C1200, e.getMessage());
					return getIncludeCallbackJson(callback, commonResult);
				}
			}
			commonResult = new CommonResult(ReturnCodeDefine.Code.C1000, ReturnCodeDefine.Msg.M1000);
		} else {
			commonResult = new CommonResult(ReturnCodeDefine.Code.C1101, ReturnCodeDefine.Msg.M1101);
		}
		return getIncludeCallbackJson(callback, commonResult);
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getPassphrase() {
		return passphrase;
	}

	public void setPassphrase(String passphrase) {
		this.passphrase = passphrase;
	}

	public static Map<Long, UserSchSessions> getUserSchSessionMap() {
		return userSchSessionMap;
	}

	public static void setUserSchSessionMap(Map<Long, UserSchSessions> userSchSessionMap) {
		SecureShellJsonpAction.userSchSessionMap = userSchSessionMap;
	}

	public HostSystem getCurrentSystem() {
		return currentSystem;
	}

	public void setCurrentSystem(HostSystem currentSystem) {
		this.currentSystem = currentSystem;
	}

	public HostSystem getPendingSystem() {
		return pendingSystem;
	}

	public void setPendingSystem(HostSystem pendingSystem) {
		this.pendingSystem = pendingSystem;
	}

	public HostSystem getSystem() {
		return system;
	}

	public void setSystem(HostSystem system) {
		this.system = system;
	}

}
